import sys
import os
from PyQt5 import  QtWidgets
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QTableWidget, QTableWidgetItem,
    QFileDialog, QPushButton, QVBoxLayout, QWidget, QHBoxLayout,
    QLineEdit, QLabel,QMessageBox
)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from utils import resource_path
image_path = resource_path("img/")

class BinaryMerger(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('bin文件合并工具 V1.0.0')
        self.setWindowIcon(QIcon(image_path+'merge.ico'))
        screen_size = QtWidgets.QDesktopWidget().screenGeometry()
        P_screen_w = int(0.5*screen_size.width())
        P_screen_h = int(0.5*screen_size.height())
        self.resize(P_screen_w, P_screen_h)

        # 中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 布局
        main_layout = QVBoxLayout()

        # 表格用于显示文件信息
        self.table_widget = QTableWidget()
        self.table_widget.setColumnCount(4)
        self.table_widget.setHorizontalHeaderLabels(['索引', '文件名', '大小', '偏移地址'])
        self.table_widget.horizontalHeader().setStretchLastSection(True)
        self.table_widget.setSelectionBehavior(QTableWidget.SelectRows)
        main_layout.addWidget(self.table_widget)

        # 文件选择和操作按钮区域
        button_layout = QHBoxLayout()

        self.source_file_button = QPushButton('源文件:')
        self.source_file_button.clicked.connect(self.select_source_file)
        button_layout.addWidget(self.source_file_button)

        self.source_file_edit = QLineEdit()
        button_layout.addWidget(self.source_file_edit)

        self.address_label = QLabel('偏移地址:')
        button_layout.addWidget(self.address_label)

        self.offset_spin_box = QLineEdit('0x00000000')
        self.offset_spin_box.setMaxLength(10)
        button_layout.addWidget(self.offset_spin_box)

        self.add_button = QPushButton('添加')
        self.add_button.clicked.connect(self.add_file)
        button_layout.addWidget(self.add_button)

        self.modify_button = QPushButton('修改')
        self.modify_button.clicked.connect(self.modify_file)
        button_layout.addWidget(self.modify_button)

        self.delete_button = QPushButton('删除')
        self.delete_button.clicked.connect(self.delete_file)
        button_layout.addWidget(self.delete_button)

        self.merge_button = QPushButton('合并')
        self.merge_button.clicked.connect(self.merge_files)
        button_layout.addWidget(self.merge_button)

        main_layout.addLayout(button_layout)
        central_widget.setLayout(main_layout)

    def select_source_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, '选择源文件', '', '二进制文件 (*.bin)')
        if file_path:
            self.source_file_edit.setText(file_path)


    def add_file(self):
        row_count = self.table_widget.rowCount()
        self.table_widget.insertRow(row_count)

        index_item = QTableWidgetItem(str(row_count))
        index_item.setFlags(Qt.ItemIsEnabled)
        self.table_widget.setItem(row_count, 0, index_item)

        file_name_item = QTableWidgetItem(self.source_file_edit.text())
        self.table_widget.setItem(row_count, 1, file_name_item)

        try:
            with open(self.source_file_edit.text(), 'rb') as f:
                size = len(f.read())
            size_item = QTableWidgetItem(str(size))
            self.table_widget.setItem(row_count, 2, size_item)
        except:
            size_item = QTableWidgetItem('0')
            self.table_widget.setItem(row_count, 2, size_item)

        offset_item = QTableWidgetItem(self.offset_spin_box.text())
        self.table_widget.setItem(row_count, 3, offset_item)

    def modify_file(self):
        selected_rows = self.table_widget.selectedItems()
        if not selected_rows:
            QMessageBox.warning(self, '警告', '请先选择要修改的行')
            return

        row = selected_rows[0].row()
        file_name_item = self.table_widget.item(row, 1)
        if file_name_item:
            file_name, _ = QFileDialog.getOpenFileName(self, '选择文件', '', '二进制文件 (*.bin)')
            if file_name:
                file_name_item.setText(file_name)

                try:
                    with open(file_name, 'rb') as f:
                        size = len(f.read())
                    size_item = QTableWidgetItem(str(size))
                    self.table_widget.setItem(row, 2, size_item)
                except:
                    size_item = QTableWidgetItem('0')
                    self.table_widget.setItem(row, 2, size_item)

                # 更新偏移地址
                offset_item = QTableWidgetItem(self.offset_spin_box.text())
                self.table_widget.setItem(row, 3, offset_item)



    def delete_file(self):
        selected_ranges = self.table_widget.selectedRanges()
        if not selected_ranges:
            QMessageBox.warning(self, '警告', '请先选择要删除的行')
            return
        selected_rows = set()
        for selected_range in selected_ranges:
            for row in range(selected_range.topRow(), selected_range.bottomRow() + 1):
                selected_rows.add(row)

        if not selected_rows:
            QMessageBox.warning(self, '警告', '请先选择要删除的行')
            return

        # 删除选中的行
        for row in sorted(selected_rows, reverse=True):
            self.table_widget.removeRow(row)

    def merge_files(self):
        # 固定生成 merge_firmware.bin
        target_file_path = os.path.join(os.getcwd(), "merge_firmware.bin")
        
        # 文件已存在提示
        if os.path.exists(target_file_path):
            reply = QMessageBox.question(self,'文件已存在','合并文件已存在，是否覆盖？',QMessageBox.Yes | QMessageBox.No)
            if reply != QMessageBox.Yes:
                return

        table_data = []
        for row in range(self.table_widget.rowCount()):
            index_item = self.table_widget.item(row, 0)
            file_name_item = self.table_widget.item(row, 1)
            size_item = self.table_widget.item(row, 2)
            offset_item = self.table_widget.item(row, 3)

            if not index_item or not file_name_item or not size_item or not offset_item:
                QMessageBox.warning(self, '警告', f'行 {row} 的数据不完整')
                continue
            index = index_item.text()
            file_name = file_name_item.text()
            size = int(size_item.text())
            offset = int(offset_item.text(), 16)
            table_data.append((index, file_name, size, offset))

        try:
            with open(target_file_path, 'wb') as target_file:
                for data in table_data:
                    file_name = data[1]
                    size = data[2]
                    offset = data[3]
                    try:
                        with open(file_name, 'rb') as source_file:
                            source_data = source_file.read()
                            if len(source_data) != size:
                                QMessageBox.warning(self, '警告', f'文件 {file_name} 的大小与预期不符')
                                continue
                            target_file.seek(offset)
                            target_file.write(source_data)
                    except FileNotFoundError:
                        QMessageBox.warning(self, '警告', f'文件 {file_name} 不存在')
        except Exception as e:
            QMessageBox.critical(self, '错误', f'合并文件时发生错误: {str(e)}')
        else:
            QMessageBox.information(self,'合并成功',f'文件已合并至：\n{target_file_path}')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    merger = BinaryMerger()
    merger.show()
    sys.exit(app.exec_())
